function doubleClick(mineSweeper, row, col) {
    let direction = [[-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1]]
    let cell = mineSweeper.cells[row][col]
    for (let [prow, pcol] of direction) {
        newrow = row + prow
        newcol = col + pcol
        if (cell.value === -1) {
            continue
        }

        if (newrow < 0 || newrow >= mineSweeper.rows) {
            continue
        }

        if (newcol < 0 || newcol >= mineSweeper.cols) {
            continue
        }

        let neighborcell = mineSweeper.cells[newrow][newcol]
        if (neighborcell.value === -1 && neighborcell.flag) {
            continue
        }
        if (neighborcell.value === -1 && neighborcell.flag === false) {
            gameover(mineSweeper)
        }
        neighborcell.open = true
        neighborcell.el.classList.add('open')
    }
}

function click(mineSweeper, row, col) {
    if (mineSweeper.state === 0) {
        gametart(mineSweeper)
    }
    if (mineSweeper.state === 2 || mineSweeper.state === 3) {
        return
    }
    let { cells } = mineSweeper
    let cell = cells[row][col]
    if (cell.flag) {
        cell.flag = false
        cell.el.classList.remove('plant')
        mineSweeper.remain++
        showRemain(mineSweeper)
        return
    }

    if (cell.value === -1) {
        gameover(mineSweeper)
    } else if (cell.value > 0) {
        cell.open = true
        cell.el.classList.add('open')

    } else if (cell.value === 0) {
        openAllSafeZones(mineSweeper, row, col)
    }
    checkGameWin(mineSweeper)

}

function rightRlick(mineSweeper, row, col) {
    if (mineSweeper.state === 0) {
        gametart(mineSweeper)
    }
    if (mineSweeper.state === 2 || mineSweeper.state === 3) {
        return
    }
    let { cells } = mineSweeper
    let cell = cells[row][col]
    if (cell.open) {
        return
    }
    if (cell.flag) {
        cell.flag = false
        cell.el.classList.remove('plant')
        mineSweeper.remain++
        showRemain(mineSweeper)
    } else {
        if (mineSweeper.remain > 0) {
            cell.flag = true
            cell.el.classList.add('plant')
            mineSweeper.remain--
            showRemain(mineSweeper)
        }

    }
    checkGameWin(mineSweeper)

}



function showRemain(mineSweeper) {
    let remainEl = document.querySelector('.gameinfo > .remain')
    remainEl.innerText = mineSweeper.remain
}

function showTimer(mineSweeper) {
    let timerEl = document.querySelector('.gameinfo > .timer')
    timerEl.innerText = mineSweeper.timer
}

function gametart(mineSweeper) {
    mineSweeper.state = 1
    mineSweeper.intervalId = setInterval(() => {
        mineSweeper.timer++
        showTimer(mineSweeper)
    }, 1000)
    let stateEl = document.querySelector('.gameinfo >.state')
    stateEl.innerHTML = ''
    stateEl.innerText = 'Running'

}

function gameover(mineSweeper) {
    mineSweeper.state = 3
    clearInterval(mineSweeper.intervalId)
    let stateEl = document.querySelector('.gameinfo > .state')
    stateEl.innerText = 'Fail!'
    openAllCells(mineSweeper)
}

function gamewin(mineSweeper) {
    mineSweeper.state = 2
    clearInterval(mineSweeper.intervalId)
    let stateEl = document.querySelector('.gameinfo > .state')
    stateEl.innerText = 'Win!'
}

function checkGameWin(mineSweeper) {
    let { rows, cols, cells } = mineSweeper
    let nopen = 0
    let flagMines = 0
    for (let row = 0; row < rows; row++) {
        for (let col = 0; col < cols; col++) {
            let cell = cells[row][col]
            if (cell.open) {
                nopen++
            }
            if (cell.flag && cell.value === -1) {
                flagMines++
            }
        }
    }
    if (nopen === mineSweeper.numberOfCells - mineSweeper.numberOfMines) {
        gamewin(mineSweeper)
    }
    if (flagMines === mineSweeper.numberOfMines) {
        gamewin(mineSweeper)
    }
}

function openAllCells(mineSweeper) {
    let { rows, cols, cells } = mineSweeper
    for (let row = 0; row < rows; row++) {
        for (let col = 0; col < cols; col++) {
            let cell = cells[row][col]
            cell.open = true
            cell.el.classList.add('open')
            if (cell.flag) {
                cell.flag = false
                cell.el.classList.remove('plant')
            }
            if (cell.value === -1) {
                cell.el.classList.add('exploded')
            }
        }
    }
}



function openAllSafeZones(mineSweeper, row, col) {
    let { rows, cols, cells } = mineSweeper
    let direction = [[-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1]]
    let cell = cells[row][col]
    cell.open = true
    cell.el.classList.add('open')
    for (let [prow, pcol] of direction) {
        newrow = row + prow
        newcol = col + pcol
        if (cell.value === -1) {
            continue
        }

        if (newrow < 0 || newrow >= rows) {
            continue
        }

        if (newcol < 0 || newcol >= cols) {
            continue
        }

        let neighborcell = cells[newrow][newcol]

        if (neighborcell.open) {
            continue
        }

        if (neighborcell.flag) {
            continue
        }

        if (neighborcell.value > 0) {
            neighborcell.open = true
            neighborcell.el.classList.add('open')
            continue
        }

        if (neighborcell.value === 0) {
            openAllSafeZones(mineSweeper, newrow, newcol)
        }
    }
}





function randomMine(nmines, rows, cols) {
    let mines = []
    let mineObject = {}

    for (let i = 0; i < nmines; i++) {
        while (true) {

            let row = Math.floor(Math.random() * rows)
            let col = Math.floor(Math.random() * cols)
            let key = `${row},${col}`
            if (key in mineObject) {
                continue
            }

            mineObject[key] = true
            mines.push([row, col])
            break

        }


    }
    return mines

}


let mineSweeper = {
    state: 0,
    timer: 0,
    flagMines: 0,
    drawMineGraph: function () {
        let mines = randomMine(this.numberOfMines, this.rows, this.cols)
        console.log(mines);
        let taEl = document.querySelector('#gameborder').querySelector('.mineGraph')
        let cells = []
        for (let row = 0; row < this.rows; row++) {
            let trEl = document.createElement('tr')
            let rowcell = []
            for (let col = 0; col < this.cols; col++) {
                let tdEl = document.createElement('td')
                let divEl = document.createElement('div')
                divEl.className = 'cell'
                divEl.innerHTML = '<div class="mine"></div><div class="flag">&#128681</div>'
                divEl.addEventListener('click', () => {
                    click(mineSweeper, row, col)
                })
                divEl.addEventListener('contextmenu', (r) => {
                    r.preventDefault()
                    rightRlick(mineSweeper, row, col)
                })
                divEl.addEventListener('dblclick', () => {
                    doubleClick(mineSweeper, row, col)
                })
                tdEl.append(divEl)
                trEl.append(tdEl)

                rowcell.push({
                    el: divEl,
                    open: false,
                    flag: false
                })
            }
            taEl.append(trEl)
            cells.push(rowcell)
        }

        
        for (let mine of mines) {
            let [Row, Col] = mine
            let cell = cells[Row][Col]
            let mineEl = cell.el.querySelector('.mine')
            mineEl.innerHTML = '&#128163'
            cell.value = -1

        }
        this.cells = cells
        showTimer(mineSweeper)
        showRemain(mineSweeper)

    }

}

function countSroudingMines(mineSweeper) {
    let direction = [[-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1]]
    let { rows, cols, cells } = mineSweeper
    for (let row = 0; row < rows; row++) {
        for (let col = 0; col < cols; col++) {
            let nmines = 0

            for (let [prow, pcol] of direction) {
                newrow = row + prow
                newcol = col + pcol

                let cell = cells[row][col]
                if (cell.value === -1) {
                    continue
                }

                if (newrow < 0 || newrow >= rows) {
                    continue
                }

                if (newcol < 0 || newcol >= cols) {
                    continue
                }

                let neighborcell = cells[newrow][newcol]

                if (neighborcell.value === -1) {
                    nmines++
                }

                if (nmines === 1) {
                    cell.el.classList.add('mine1')
                } else if (nmines === 2) {
                    cell.el.classList.add('mine2')
                } else if (nmines === 3) {
                    cell.el.classList.add('mine3')
                }

                cell.value = nmines

                if (cell.value === 0) {
                    continue
                }
                let mineEl = cell.el.querySelector('.mine')
                mineEl.innerText = nmines


            }
        }
    }
}



function easy() {
    let gameborderEl = document.querySelector('#gameborder').querySelector('.mineGraph')
    gameborderEl.innerHTML = ' '
    mineSweeper.state = 0
    mineSweeper.timer = 0
    mineSweeper.rows = 9
    mineSweeper.cols = 9
    mineSweeper.numberOfMines = 10
    mineSweeper.remain = 10
    mineSweeper.numberOfCells = mineSweeper.rows * mineSweeper.cols
    mineSweeper.drawMineGraph()
    countSroudingMines(mineSweeper)
    let stateEl = document.querySelector('.gameinfo >.state')
    stateEl.innerHTML = '未开始'


}

function normal() {
    let gameborderEl = document.querySelector('#gameborder').querySelector('.mineGraph')
    gameborderEl.innerHTML = ' '
    mineSweeper.state = 0
    mineSweeper.timer = 0
    mineSweeper.rows = 16
    mineSweeper.cols = 16
    mineSweeper.numberOfMines = 40
    mineSweeper.remain = 40
    mineSweeper.numberOfCells = mineSweeper.rows * mineSweeper.cols
    mineSweeper.drawMineGraph()
    countSroudingMines(mineSweeper)
    let stateEl = document.querySelector('.gameinfo >.state')
    stateEl.innerHTML = '未开始'

}

function hard() {
    let gameborderEl = document.querySelector('#gameborder').querySelector('.mineGraph')
    gameborderEl.innerHTML = ' '
    mineSweeper.state = 0
    mineSweeper.timer = 0
    mineSweeper.rows = 16
    mineSweeper.cols = 30
    mineSweeper.numberOfMines = 99
    mineSweeper.remain = 99
    mineSweeper.numberOfCells = mineSweeper.rows * mineSweeper.cols
    mineSweeper.drawMineGraph()
    countSroudingMines(mineSweeper)
    let stateEl = document.querySelector('.gameinfo >.state')
    stateEl.innerHTML = '未开始'

}

function modeSelect(mode) {
    if (mode == 0) {
        easy()
    }
    if (mode == 1) {
        normal()
    }
    if (mode == 2) {
        hard()
    }
}

function day() {
    let el = document.querySelector('.body')
    el.classList.remove('night')
    el.classList.add('day')
}

function night() {
    let el = document.querySelector('.body')
    el.classList.remove('day')
    el.classList.add('night')
}

function main() {
    easy()
    let stateEl = document.querySelector('.gameinfo >.state')
    stateEl.innerHTML = '未开始'

}
